--[[
-- @Author:			
-- @DateTime:	2020-10-30 23:05:48
-- @Description: 客户端连接

--]]


local skynet = require("skynet")
local Socket = require("skynet.socket")



--消息打包类
local ClientNet = class("ClientNet")


function ClientNet:ctor()
    self.fd = nil
    self.ip = nil
    self.port = nil
    self.last_package = ""
    self.msg_callbacks = {} --消息回调列表

    self.client_pack = new("client_pack")


    --接收消息
    skynet.fork(function() 
        while true do
            -- print(">>>M:recv_loop>>>")
            if self.fd then
                local str = Socket.read(self.fd)
                if str then
                    self:receive(str)
                else
                    g.Log():Error("接收数据错误,关闭fd:", self.fd)
                    self:close()                
                end                
            else
                skynet.sleep(100)
            end
        end
    end)       
end

--取大端2个字节
function ClientNet:readShortBig( text ) --big endian
    return text:byte(1)*256 + text:byte(2)
end

--包长度2字节（skynet 规定头2个字节为包长度
function ClientNet:unpackPackage(text)
    local size = #text
    if size < 2 then
        return nil, text
    end
    local pack_size = self:readShortBig(text)
    if size < pack_size + 2 then
        return nil, text
    end
    local offset = 2
    local msg = text:sub(offset + 1, offset + pack_size)
    local last = text:sub(offset + 1 + pack_size)
    return msg, last
end

--连接socket
function ClientNet:connect(ip, port)
    if not ip or not port then 
        print("ClientNet:connect ip port is nill___")
        return false
    end
    self.ip = ip
    self.port = port     
    self.fd = Socket.open(ip, port)
    if not self.fd then
        print("连接 "..ip..":"..port.."失败")
        return false
    end
    print("########连接"..ip..":"..port.."成功#########")
    return true
end

function ClientNet:receive(str)
    -- print("收到数据"..#str)
    self.last_package = self.last_package .. str
    local msg
    while #self.last_package > 0 do
        msg, self.last_package = self:unpackPackage(self.last_package)
        if not msg then
            break 
        end
        if msg then                
            local msg_id, msg_name, msg_data = self.client_pack:unpack(msg, #msg)
            g.MsgDis():dispatchMessage(_, _, msg_name, msg_data)
        end
    end
end

function ClientNet:close()
    print("____________ClientNet close__________",self.fd)
    if self.fd then 
        Socket.close(self.fd)
    end
    self.fd = nil
end

function ClientNet:send(msg_name, msg_body, conn_type)
    if not self.fd then 
        local conn = self:connect(self.ip, self.port)
        if not conn then 
            --连接失败            
            return 
        end
    end
    self.client_pack:send(self.fd, msg_name, msg_body, conn_type)
end

return ClientNet